package com.imay.videorecord.encoder.edit;

import android.content.Context;
import android.media.MediaCodecInfo;
import android.util.Log;

import com.imay.videorecord.FFmpegKit;
import com.imay.videorecord.encoder.compress.AndroidMediaObjectFactory;
import com.imay.videorecord.encoder.compress.AudioFormatAndroid;
import com.imay.videorecord.encoder.compress.VideoFormatAndroid;

import org.m4m.AudioFormat;
import org.m4m.IProgressListener;
import org.m4m.MediaComposer;
import org.m4m.MediaFileInfo;
import org.m4m.Uri;
import org.m4m.VideoFormat;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import static com.imay.videorecord.utils.SDKFileUtils.fileExist;

/**
 *
 */
public class VideoEditor {


    private final AndroidMediaObjectFactory factory;
    private MediaComposer mediaComposer;
    private MediaFileInfo mediaFileInfo;
    private AudioFormat audioFormat;
    private VideoFormat videoFormat;

    private long duration;

    protected int videoWidthOut = 640;
    protected int videoHeightOut = 640;

    protected int videoWidthIn = 640;
    protected int videoHeightIn = 640;

    protected final String videoMimeType = "video/avc";
    protected int videoBitRateInKBytes = 1000;
    protected final int videoFrameRate = 30;

    protected final int videoIFrameInterval = 1;
    // Audio
    protected final String audioMimeType = "audio/mp4a-latm";
    protected final int audioSampleRate = 44100;
    protected final int audioChannelCount = 2;

    protected final int audioBitRate = 80 * 1024;


    public VideoEditor(Context context) {
        factory = new AndroidMediaObjectFactory(context.getApplicationContext());
    }

    /**
     * ffmpeg -threads 4 -i "+videoUrl+" -acodec copy -r 30 -vcodec libx264 -s 480x480 -b:v 500 -crf:v 24 "+ path
     *
     * @param srcPath
     * @param dstPath
     */
    public void executeVideoCompress(String srcPath, String dstPath, FFmpegKit.KitInterface kitInterface) {
        if (fileExist(srcPath)) {

            List<String> cmdList = new ArrayList<String>();

            cmdList.add("ffmpeg");

            cmdList.add("-threads");
            cmdList.add("4");

            cmdList.add("-i");
            cmdList.add(srcPath);

            cmdList.add("-acodec");
            cmdList.add("copy");

            cmdList.add("-r");
            cmdList.add("30");

            cmdList.add("-vcodec");
            cmdList.add("libx264");

            cmdList.add("-preset");
            cmdList.add("veryfast");

            cmdList.add("-s");
            cmdList.add("640x640");

            cmdList.add("-b:v");
            cmdList.add("500");

            cmdList.add("-crf:v");
            cmdList.add("28");

            cmdList.add(dstPath);
            StringBuffer stringBuffer = new StringBuffer();
            String[] command = new String[cmdList.size()];
            for (int i = 0; i < cmdList.size(); i++) {
                command[i] = (String) cmdList.get(i);
                stringBuffer.append(cmdList.get(i) + " ");
            }
            Log.i(VideoEditor.class.getSimpleName(), stringBuffer.toString());
            FFmpegKit.execute(command, kitInterface);
        }
    }

    /**
     * 压缩视频
     *
     * @param srcPath
     * @param dstPath
     * @param progressListener
     */
    public void executeVideoCompressMediaMuxer(String srcPath, String dstPath, IProgressListener progressListener) {
        try {
            Uri uri = new Uri(srcPath);
            mediaFileInfo = new org.m4m.MediaFileInfo(factory);
            mediaFileInfo.setUri(uri);
            getFileInfo();

            mediaComposer = new MediaComposer(factory, progressListener);
            setTranscodeParameters(mediaComposer, uri, dstPath);
            mediaComposer.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void stopTranscode() {
        mediaComposer.stop();
    }

    /**
     * 获取信息
     */
    protected void getFileInfo() {
        try {
            duration = mediaFileInfo.getDurationInMicroSec();

            audioFormat = (org.m4m.AudioFormat) mediaFileInfo.getAudioFormat();
            if (audioFormat == null) {
                return;
            }

            videoFormat = (org.m4m.VideoFormat) mediaFileInfo.getVideoFormat();
            if (videoFormat == null) {
                return;
            } else {
                videoWidthIn = videoFormat.getVideoFrameSize().width();
                videoHeightIn = videoFormat.getVideoFrameSize().height();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 设置转码路径和帧大小
     *
     * @param mediaComposer
     * @param uri
     * @param dstPath
     * @throws IOException
     */
    public void setTranscodeParameters(MediaComposer mediaComposer, Uri uri, String dstPath) throws IOException {
        mediaComposer.addSourceFile(uri);
        mediaComposer.setTargetFile(dstPath);


        configureVideoEncoder(mediaComposer, videoWidthOut, videoHeightOut);
        configureAudioEncoder(mediaComposer);
    }

    protected void configureVideoEncoder(org.m4m.MediaComposer mediaComposer, int width, int height) {
        VideoFormatAndroid videoFormat = new VideoFormatAndroid(videoMimeType, width, height);

        videoFormat.setVideoBitRateInKBytes(videoBitRateInKBytes);
        videoFormat.setVideoFrameRate(videoFrameRate);
        videoFormat.setVideoIFrameInterval(videoIFrameInterval);

        mediaComposer.setTargetVideoFormat(videoFormat);
    }

    protected void configureAudioEncoder(org.m4m.MediaComposer mediaComposer) {
        AudioFormatAndroid aFormat = new AudioFormatAndroid(audioMimeType, audioFormat.getAudioSampleRateInHz(), audioFormat.getAudioChannelCount());

        aFormat.setAudioBitrateInBytes(audioBitRate);
        aFormat.setAudioProfile(MediaCodecInfo.CodecProfileLevel.AACObjectLC);

        mediaComposer.setTargetAudioFormat(aFormat);
    }
}
